﻿@using System.Web.Mvc
@using System.Web.Mvc.Html
@using System.Web.Routing
@using NuGetGallery
@using NuGetGallery.Helpers
@using NuGetGallery.Configuration
@using NuGet.Services.Entities
@using NuGet.Services.Licenses

@helper GetColumnClasses(string screenSize, int? columns)
{
    const int TotalColumns = 12;
    if (!columns.HasValue)
    {
        return;
    }

    var offset = (TotalColumns - columns.Value) / 2;
    var columnsClass = "col-" + screenSize + "-" + columns.Value;
    var offsetClass = offset == 0 ? string.Empty : " col-" + screenSize + "-offset-" + offset;

    @(columnsClass + " " + offsetClass)
}

@helper GetColumnClasses(dynamic viewBag)
{
    int? smPageColumns = 12;
    if (viewBag.SmPageColumns != null)
    {
        smPageColumns = (int)viewBag.SmPageColumns;
    }

    int? mdPageColumns = null;
    if (viewBag.MdPageColumns != null)
    {
        mdPageColumns = (int)viewBag.MdPageColumns;
    }

    @(GetColumnClasses("sm", smPageColumns) + " " + GetColumnClasses("md", mdPageColumns))
}

@helper Alert(Func<MvcHtmlString, HelperResult> htmlContent, string subclass, string icon, bool isAlertRole = false)
{
    <div class="icon-text alert alert-@subclass" @if (isAlertRole) { <text> role="alert" aria-live="assertive" </text> }>
        <i class="ms-Icon ms-Icon--@icon" aria-hidden="true"></i>
        @htmlContent(MvcHtmlString.Empty)
    </div>
}

@helper Alert(string htmlContent, string subclass, string icon, bool isAlertRole = false)
{
    @Alert(s => new HelperResult(t => t.Write(htmlContent)), subclass, icon, isAlertRole);
}

@helper AlertInfo(string htmlContent, bool isAlertRole = false)
{
    @Alert(htmlContent, "info", "Info", isAlertRole)
}

@helper AlertInfo(Func<MvcHtmlString, HelperResult> htmlContent, bool isAlertRole = false)
{
    @Alert(htmlContent, "info", "Info", isAlertRole)
}

@helper AlertWarning(Func<MvcHtmlString, HelperResult> htmlContent, bool isAlertRole = false)
{
    @Alert(htmlContent, "warning", "Warning", isAlertRole)
}

@helper AlertDanger(Func<MvcHtmlString, HelperResult> htmlContent, bool isAlertRole = true)
{
    @Alert(htmlContent, "danger", "ErrorBadge", isAlertRole)
}

@helper AlertPasswordDeprecation()
{
    @AlertWarning(
    @<text>
        NuGet.org password login is no longer supported. Please use a Microsoft account to sign into NuGet gallery.
    </text>
    )
}

@helper ErrorPage(UrlHelper url, System.Web.Mvc.HtmlHelper html, string errorNumber, string errorName, Func<MvcHtmlString, HelperResult> errorTextMain, Func<MvcHtmlString, HelperResult> errorTextSub = null)
{
    <section role="main" class="container main-container">
        <div class="row page-error">
            <div class="col-sm-12 ms-fontWeight-light">
                <p class="oops">Oops!</p>
                <p class="error-title">Error @errorNumber - @errorName</p>
                <div class="error-text">
                    <div class="text-main">
                        @errorTextMain(MvcHtmlString.Empty)
                    </div>
                    @if (errorTextSub != null)
                    {
                        <div class="text-subtext">
                            @errorTextSub(MvcHtmlString.Empty)
                        </div>
                    }
                </div>

                <p class="error-action">Get me out of here! <a href="@url.Home()">Go home</a></p>
                <p class="error-action">Wondering if NuGet is down? <a href="https://status.nuget.org/">Check our status</a></p>
                <p class="error-action">Looking for a package? <a href="@url.PackageList()">Try searching</a></p>
                <p class="error-action">Package you're looking for doesn't exist? <a href="https://docs.microsoft.com/en-us/nuget/quickstart/create-and-publish-a-package">Make one</a></p>
                <p class="error-action">Pretty sure we messed up? <a href="https://github.com/NuGet/NuGetGallery/issues">File a bug</a></p>
                <p class="error-action">Can't get enough NuGet? <a href="https://twitter.com/nuget">Follow us</a></p>
            </div>
        </div>
    </section>
}

@helper PreviousNextPager(IPreviousNextPager pager)
{
    if (pager.HasNextPage || pager.HasPreviousPage)
    {
        <ul class="pager">
            <li class="previous">
                @if (pager.HasPreviousPage)
                {
                    <a href="@pager.PreviousPageUrl" title="Go to the previous page.">Previous</a>
                }
                else
                {
                    <text>Previous</text>
                }
            </li>
            <li class="next">
                @if (pager.HasNextPage)
                {
                    <a href="@pager.NextPageUrl" title="Go to the next page.">Next</a>
                }
                else
                {
                    <text>Next</text>
                }
            </li>
        </ul>
    }
}

@helper ImageFallback(string url)
{
    <text>onerror="this.src='@url'; this.onerror = null;"</text>
}

@helper Option(string value, string label, string currentValue)
{
    <option value="@value" @if (value == currentValue)
                           {
                               <text>selected="selected"</text>
                           }>@label</option>
}

@helper UploadSequence(int currentStep)
{
    <ol class="sequence">
        @SequenceStep(1, "Upload", currentStep)
        @SequenceStep(2, "Verify Details", currentStep)
    </ol>
    <div class="clear-fix"><!--Sad Panda--></div>
}

@helper SequenceStep(int step, string caption, int currentStep)
{
    if (currentStep > step)
    {
        <li class="past">@caption</li>
    }
    else if (currentStep == step)
    {
        <li class="current">@caption</li>
    }
    else
    {
        <li>@caption</li>
    }
}

@helper GravatarImage(UrlHelper url, string email, string username, int size)
{
    @GravatarImage(url, email, username, size, responsive: false);
}

@helper GravatarImage(UrlHelper url, string email, string username, int size, bool responsive)
{
    @GravatarHelper.Image(url, email, username, size, responsive);
}

@helper UserLinkWithIcon(UrlHelper url, BasicUserViewModel user)
{
    <span class="ms-noWrap">
        @if (user.IsOrganization)
        {
            <i class="ms-Icon ms-Icon--Group" aria-hidden="true"></i>
        }
        <a href="@url.User(user.Username)" title="@user.Username">@user.Username.Abbreviate(15)</a>
    </span>
}

@helper WriteMeta(string name, string val)
{
    if (!String.IsNullOrEmpty(val))
    {
        <meta name="deployment-@name" content="@val" />
    }
}

@helper ReleaseMeta()
{
    // Get Version info
    var ver = ApplicationVersionHelper.GetVersion();

    if (ver.Present)
    {
        WriteMeta("branch", ver.Branch);
        WriteMeta("commit", ver.ShortCommit);
        WriteMeta("time", ver.BuildDateUtc == DateTime.MinValue ? null : ver.BuildDateUtc.ToString("O"));
    }
}

@helper InstrumentationScript(dynamic viewBag)
{
    // Get instrumentation keys
    var config = DependencyResolver.Current.GetService<IGalleryConfigurationService>();
    var iKey = config == null ? string.Empty : config.Current.AppInsightsInstrumentationKey;
    var samplingPct = config == null ? 100 : config.Current.AppInsightsSamplingPercentage;
    var tenantKey = config == null ? string.Empty : config.Current.InternalMicrosoftTenantKey;

    if (!string.IsNullOrEmpty(iKey) || !string.IsNullOrEmpty(tenantKey))
    {
        bool canWriteAnalyticsCookies = viewBag.CanWriteAnalyticsCookies ?? false;
        if (canWriteAnalyticsCookies)
        {
            if (!string.IsNullOrEmpty(tenantKey))
            {
                @System.Web.Optimization.Scripts.Render("~/Scripts/gallery/instrumentation.min.js")
                <script type="text/javascript">
                if (window.initializeNuGetInstrumentation) {
                    window.NuGetInstrumentation = window.initializeNuGetInstrumentation({
                        appInsightsInstrumentationKey: "@iKey",
                        appInsightsSamplingPercentage: @samplingPct,
                        tenantKey: "@tenantKey",
                    });
                }
                </script>
            }
            else
            {
            <script type="text/javascript">
                var appInsights = window.appInsights || function (config) {
                    function s(config) {
                        t[config] = function () {
                            var i = arguments;
                            t.queue.push(function () { t[config].apply(t, i) })
                        }
                    }

                    var t = { config: config }, r = document, f = window, e = "script", o = r.createElement(e), i, u;
                    for (o.src = config.url || "//az416426.vo.msecnd.net/scripts/a/ai.0.js", r.getElementsByTagName(e)[0].parentNode.appendChild(o), t.cookie = r.cookie, t.queue = [], i = ["Event", "Exception", "Metric", "PageView", "Trace"]; i.length;) s("track" + i.pop());
                    return config.disableExceptionTracking || (i = "onerror", s("_" + i), u = f[i], f[i] = function (config, r, f, e, o) {
                        var s = u && u(config, r, f, e, o);
                        return s !== !0 && t["_" + i](config, r, f, e, o), s
                    }), t
                }({
                    instrumentationKey: '@(iKey)',
                    samplingPercentage: @(samplingPct)
                });

                window.appInsights = appInsights;
                appInsights.trackPageView();
            </script>
            }
        }
    }
}

@helper ReleaseTag()
{
    // Get Version info and gallery brand name
    var ver = ApplicationVersionHelper.GetVersion();
    var config = DependencyResolver.Current.GetService<IGalleryConfigurationService>();
    string brand = config == null ? "" : config.Current.Brand;

<!--
@if (ver.Present)
{
    @:This is the @brand version @ver.Version.
    if(!String.IsNullOrEmpty(ver.ShortCommit)) {
        @:Deployed from @ver.ShortCommit Link: @(ver.CommitUri != null ? ver.CommitUri.AbsoluteUri.Replace("git://github.com", "https://github.com") : "")
    }

    if(!String.IsNullOrEmpty(ver.Branch)) {
        @:Built on @ver.Branch Link: @(ver.BranchUri != null ? ver.BranchUri.AbsoluteUri : "")
    }

    if(ver.BuildDateUtc != DateTime.MinValue) {
        @:Built on @ver.BuildDateUtc.ToString("O")
    }
} else {
    @:This is the @brand
}
@if (config != null && config.Current != null && !string.IsNullOrWhiteSpace(config.Current.DeploymentLabel)) {
    @:Deployment label: @config.Current.DeploymentLabel
}
    You are on @HostMachine.Name.
-->
@* A little quick-n-dirty code to display the current machine *@
@* In Azure, we want the Instance ID. The Machine Name is total garbage *@
}

@helper CookieComplianceScript()
{
    <script src="https://wcpstatic.microsoft.com/mscc/lib/v2/wcp-consent.js"></script>
}

@helper AnalyticsScript(dynamic viewBag)
{
    var config = DependencyResolver.Current.GetService<IGalleryConfigurationService>();
    if (config != null)
    {
        var propertyId = config.Current.GoogleAnalyticsPropertyId;
        if (!string.IsNullOrEmpty(propertyId))
        {
            bool canWriteAnalyticsCookies = viewBag.CanWriteAnalyticsCookies ?? false;
            if (canWriteAnalyticsCookies)
            {
                var obfuscatedRequest = ObfuscationHelper.ObfuscateRequestUrl(new HttpContextWrapper(HttpContext.Current), RouteTable.Routes);
                <script>
                    (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
                    (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
                    m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
                    })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

                    ga('create', '@propertyId', {
                        'cookieDomain': 'none',
                        'cookieExpires': 60 * 60 * 24 * 365,
                    });

                    ga('set', 'anonymizeIp', true);
                    ga('set', 'page', '@obfuscatedRequest');
                    ga('set', 'title', '');
                    ga('send', 'pageview');
                </script>
            }
        }
    }
}

@helper UsabillaButton(UrlHelper url, dynamic viewBag)
{
    if (GetUsabillaButtonIdOrNull(viewBag) != null)
    {
<div class="usabilla-button" id="usabilla-button" style="display: none">
    <a tabindex="0" id="usbl-integrated-button" href="#" role="button">
        <img width="40" height="130" src="~/Content/gallery/img/feedback.svg" alt="Usabilla Feedback"
                @ViewHelpers.ImageFallback(url.Absolute("~/Content/gallery/img/feedback-40x130.png")) />
    </a>
</div>
    }
}

@helper UsabillaScript(dynamic viewBag)
{
    var buttonId = GetUsabillaButtonIdOrNull(viewBag);
    if (buttonId != null)
    {
        var obfuscatedPath = ObfuscationHelper.ObfuscateRequestUrl(new HttpContextWrapper(HttpContext.Current), RouteTable.Routes);
<!-- begin usabilla live embed code -->
<script type="text/javascript">
/*{literal}<![CDATA[*/window.lightningjs||function(c){function g(b,d){d&&(d+=(/\?/.test(d)?"&":"?")+"lv=1");c[b]||function(){var i=window,h=document,j=b,g=h.location.protocol,l="load",k=0;(function(){function b(){a.P(l);a.w=1;c[j]("_load")}c[j]=function(){function m(){m.id=e;return c[j].apply(m,arguments)}var b,e=++k;b=this&&this!=i?this.id||0:0;(a.s=a.s||[]).push([e,b,arguments]);m.then=function(b,c,h){var d=a.fh[e]=a.fh[e]||[],j=a.eh[e]=a.eh[e]||[],f=a.ph[e]=a.ph[e]||[];b&&d.push(b);c&&j.push(c);h&&f.push(h);return m};return m};var a=c[j]._={};a.fh={};a.eh={};a.ph={};a.l=d?d.replace(/^\/\//,(g=="https:"?g:"http:")+"//"):d;a.p={0:+new Date};a.P=function(b){a.p[b]=new Date-a.p[0]};a.w&&b();i.addEventListener?i.addEventListener(l,b,!1):i.attachEvent("on"+l,b);var q=function(){function b(){return["<head></head><",c,' onload="var d=',n,";d.getElementsByTagName('head')[0].",d,"(d.",g,"('script')).",i,"='",a.l,"'\"></",c,">"].join("")}var c="body",e=h[c];if(!e)return setTimeout(q,100);a.P(1);var d="appendChild",g="createElement",i="src",k=h[g]("div"),l=k[d](h[g]("div")),f=h[g]("iframe"),n="document",p;k.style.display="none";e.insertBefore(k,e.firstChild).id=o+"-"+j;f.frameBorder="0";f.id=o+"-frame-"+j;/MSIE[ ]+6/.test(navigator.userAgent)&&(f[i]="javascript:false");f.allowTransparency="true";l[d](f);try{f.contentWindow[n].open()}catch(s){a.domain=h.domain,p="javascript:var d="+n+".open();d.domain='"+h.domain+"';",f[i]=p+"void(0);"}try{var r=f.contentWindow[n];r.write(b());r.close()}catch(t){f[i]=p+'d.write("'+b().replace(/"/g,String.fromCharCode(92)+'"')+'");d.close();'}a.P(2)};a.l&&setTimeout(q,0)})()}();c[b].lv="1";return c[b]}var o="lightningjs",k=window[o]=g(o);k.require=g;k.modules=c}({});
window.usabilla_live = lightningjs.require("usabilla_live", "//w.usabilla.com/@(buttonId).js");
/*]]>{/literal}*/</script>
<!-- end usabilla live embed code -->
<script type="text/javascript">
window.nuget.enableUsabilla('@obfuscatedPath');
</script>
    }
}

@helper AccordionBar(
    string groupName,
    WebViewPage page,
    string title,
    string subtitle = null,
    bool enabled = true,
    string formModelStatePrefix = null,
    Func<AccordionHelper, HelperResult> actions = null,
    Func<AccordionHelper, HelperResult> content = null
)
{
Func<AccordionHelper, HelperResult> titleTemplate = null;
if (!string.IsNullOrEmpty(title))
{
    titleTemplate = new Func<AccordionHelper, HelperResult>(@<text>@title</text>);
    }

    Func<AccordionHelper, HelperResult> subtitleTemplate = null;
    if (!string.IsNullOrEmpty(subtitle))
    {
        subtitleTemplate = new Func<AccordionHelper, HelperResult>(@<text>@subtitle</text>);
    }

    @AccordionBar(groupName,
        page,
        titleTemplate,
        subtitleTemplate,
        enabled,
        formModelStatePrefix,
        actions,
        content)
}

@helper AccordionBar(
    string groupName,
    WebViewPage page,
    Func<AccordionHelper, HelperResult> title,
    Func<AccordionHelper, HelperResult> subtitle = null,
    bool enabled = true,
    string formModelStatePrefix = null,
    Func<AccordionHelper, HelperResult> actions = null,
    Func<AccordionHelper, HelperResult> content = null,
    bool expanded = false
)
{
    @* Calculate Accordion Index *@
string dataKey = "___AccordionCounter_" + groupName;
int lastId = (int)(HttpContext.Current.Items[dataKey] ?? 0);
int id = lastId + 1;
HttpContext.Current.Items[dataKey] = id;
string name = groupName + "-" + id.ToString();
string actionsId = name + "-actions"; 

var hlp = new AccordionHelper(name, formModelStatePrefix, expanded, page);
    <li id="@hlp.ItemId" class="accordion-item @(enabled ? "accordion-item-enabled" : "accordion-item-disabled")">
        <div class="accordion-item-header">
            @if (actions != null)
            {
                <div class="accordion-item-actions" id="@actionsId" >
                    @actions(hlp)
                </div>
            }
            <span class="accordion-item-title">
                @title(hlp)
            </span>
            @if (subtitle != null)
            {
                <span class="accordion-item-subtitle">
                    @subtitle(hlp)
                </span>
            }
        </div>
        @if (content != null)
        {
            <div id="@hlp.ContentDropDownId" class="accordion-item-content @(!expanded ? hlp.ContentHiddenClass : string.Empty)">
                @content(hlp)
            </div>
        }
    </li>
}

@helper AjaxAntiForgeryToken(System.Web.Mvc.HtmlHelper html)
{
    <form aria-hidden="true" id="AntiForgeryForm">
        @html.AntiForgeryToken()
    </form>
}

@functions
{
    public static List<string> GetSections(dynamic viewBag)
    {
        var sections = viewBag.Sections as Lazy<List<string>>;
        return sections == null ? null : sections.Value;
    }

    public static void AddSection(dynamic viewBag, string id)
    {
        var sections = GetSections(viewBag);
        if (sections != null)
        {
            sections.Add(id);
        }
    }
}

@helper SectionsScript(WebViewPage viewPage)
{
    var viewSections = GetSections(viewPage.ViewBag);
    if (viewSections != null)
    {
        <script type="text/javascript">
            var sections = @viewPage.Html.Raw(Json.Encode(viewSections));
            for (var i in sections) {
                var configureSection = function (section) {
                    var containerId = section + "-container";
                    window.nuget.configureExpanderHeading(containerId);

                    // Configure the cancel button to close the section when it's clicked
                    $("#cancel-" + section).click(function (e) {
                        // Collapse the container.
                        $("#" + containerId).collapse('hide');

                        // Prevent navigation.
                        e.preventDefault();

                        // Reset the form.
                        var formElement = $("#" + containerId + " form")[0];
                        if (formElement) {
                            formElement.reset();
                        }

                        // Clear values.
                        $("#" + containerId + " input[type='text']").val("");
                        $("#" + containerId + " input[type='password']").val("");

                        // Reset the validation state.
                        if (formElement) {
                            window.nuget.resetFormValidation(formElement);
                        }
                    });
                }

                configureSection(sections[i]);
            }
        </script>
    }
}

@helper Section(
        WebViewPage viewPage,
        string id,
        string title,
        Func<MvcHtmlString, HelperResult> content,
        bool expanded = true,
        string expandedIcon = "ChevronDown",
        string collapsedIcon = "ChevronRight",
        string disabledIcon = "Lock",
        bool disabled = false)
{
    @Section(viewPage,
        id,
        @<text>@title</text>,
        @<text></text>,
        content,
        expanded,
        expandedIcon,
        collapsedIcon);
}

@helper Section(
            WebViewPage viewPage,
            string id,
            Func<MvcHtmlString, HelperResult> title,
            Func<MvcHtmlString, HelperResult> data,
            Func<MvcHtmlString, HelperResult> content,
            bool expanded = false,
            string expandedIcon = "ChevronDown",
            string collapsedIcon = "ChevronRight",
            string disabledIcon = "Lock",
            bool disabled = false)
{
    if (!disabled)
    {
        AddSection(viewPage.ViewBag, id);
    }

    <div class="clearfix">
        <div class="form-section-title">
            <h2>
                @if (!disabled)
                {
                    <a href="#" role="button" data-toggle="collapse" data-target="#@id-container"
                        aria-expanded="@(expanded ? "true" : "false")" aria-controls="@id-container" id="show-@id-container">
                        <i class="ms-Icon ms-Icon--@(expanded ? expandedIcon : collapsedIcon)"
                            aria-hidden="@(expanded ? "false" : "true")"></i>
                        <span>@title(MvcHtmlString.Empty)</span>
                    </a>
                }
                else
                {
                    <i class="ms-Icon ms-Icon--@disabledIcon" aria-hidden="true"></i>
                    <span>@title(MvcHtmlString.Empty)</span>
                }
            </h2>
        </div>
        <div class="form-section-data">
            @data(MvcHtmlString.Empty)
        </div>
    </div>
    if (!disabled)
    {
        <div class="panel panel-default panel-collapse collapse @(expanded ? "in" : string.Empty)"
                aria-expanded="@(expanded ? "true" : "false")" id="@id-container">
            <div class="panel-body">
                @content(MvcHtmlString.Empty)
            </div>
        </div>
    }
}

@helper Breadcrumb(bool showDivider, params Func<MvcHtmlString, HelperResult>[] segments)
{
    <h1 role="list" class="ms-font-xl breadcrumb-title">
        @for (int i = 0; i < segments.Length; i++)
        {
            <span role="listitem" class="ms-noWrap">@segments[i](MvcHtmlString.Empty)</span>

            if (i < segments.Length - 1)
            {
                <i class="ms-Icon ms-Icon--ChevronRight ms-font-m" aria-hidden="true"></i>
            }
        }
    </h1>
    if (showDivider)
    {
        <hr class="breadcrumb-divider" />
    }
}

@helper BreadcrumbWithProfile(UrlHelper url, User currentUser, bool showDivider, params Func<MvcHtmlString, HelperResult>[] segments)
{
    var newSegments = new Func<MvcHtmlString, HelperResult>[] 
    { 
        @<text><a href="@url.User(currentUser.Username)" aria-label="View my profile"><i class="ms-Icon ms-Icon--Contact ms-font-l" aria-hidden="true"></i></a></text> 
    }.Concat(segments).ToArray();

    @Breadcrumb(showDivider, newSegments);
}

@helper PackagesBreadcrumb(UrlHelper url, User currentUser, bool showDivider, params Func<MvcHtmlString, HelperResult>[] segments)
{
    var newSegments = new Func<MvcHtmlString, HelperResult>[]
    {
        @<text><a href="@url.ManageMyPackages()">Packages</a></text>
    }.Concat(segments).ToArray();

    @BreadcrumbWithProfile(url, currentUser, showDivider, newSegments);
}

@helper OrganizationsBreadcrumb(UrlHelper url, User currentUser, bool showDivider, params Func<MvcHtmlString, HelperResult>[] segments)
{
    var newSegments = new Func<MvcHtmlString, HelperResult>[]
    {
        @<text><a href="@url.ManageMyOrganizations()">Organizations</a></text>
    }.Concat(segments).ToArray();

    @BreadcrumbWithProfile(url, currentUser, showDivider, newSegments);
}

@helper RecaptchaScripts(string reCaptchaPublicKey, string submitId)
{
    if (!string.IsNullOrEmpty(reCaptchaPublicKey))
    {
        <script src='https://www.google.com/recaptcha/api.js' async defer></script>
        <script type="text/javascript">
            var $submit = $('@("#" + submitId)');
            $submit.before(
                '<div id="recaptcha" class="g-recaptcha" '
                + 'data-sitekey="@reCaptchaPublicKey" data-size="invisible" '
                + 'data-callback="onSubmit" data-tabindex="-1"></div>');

            var $form = $submit.parents('form')
            $submit.click(function (e) {
                if ($form.valid()) {
                    e.preventDefault();
                    grecaptcha.execute();
                }
            });

            function onSubmit(token) {
                $form.submit();
            }
        </script>
    }
}

@helper PostLink(
    System.Web.Mvc.WebViewPage page,
    string formId,
    Func<MvcHtmlString, HelperResult> htmlContent,
    string actionName,
    string controllerName,
    string role,
    string area = "",
    Dictionary<string, string> formValues = null)
{
    using (page.Html.BeginForm(
        actionName,
        controllerName,
        new { area = area },
        FormMethod.Post,
        new { id = formId }))
    {
        @page.Html.AntiForgeryToken();
        if (formValues != null)
        {
            foreach (var pair in formValues)
            {
                <input type="hidden" name="@pair.Key" value="@pair.Value" />
            }
        }
    }
    <a href="#" class="post-link" data-form-id="@formId" role="@role">@htmlContent(MvcHtmlString.Empty)</a>
}

@helper PostLink(
    System.Web.Mvc.WebViewPage page,
    string formId,
    string linkText,
    string actionName,
    string controllerName,
    string role,
    string area = "",
    Dictionary<string, string> formValues = null)
{
    @PostLink(
        page,
        formId,
        @<text>@linkText</text>,
        actionName,
        controllerName,
        role,
        area,
        formValues);
}

@functions
{
    public static string GetUsabillaButtonIdOrNull(dynamic viewBag)
    {
        var config = DependencyResolver.Current.GetService<IGalleryConfigurationService>();
        if (config != null)
        {
            var buttonId = config.Current.UsabillaFeedbackButtonId;
            if (!string.IsNullOrWhiteSpace(buttonId))
            {
                var featureFlagService = DependencyResolver.Current.GetService<IFeatureFlagService>();
                if (featureFlagService.IsUsabillaButtonEnabledOnEveryPage())
                {
                    bool canWriteAnalyticsCookies = viewBag.CanWriteAnalyticsCookies ?? false;
                    if (canWriteAnalyticsCookies)
                    {
                        return buttonId;
                    }
                }
            }
        }

        return null;
    }

    public static bool IsLicenseOrException(CompositeLicenseExpressionSegment segment)
    {
        return segment.Type == CompositeLicenseExpressionSegmentType.LicenseIdentifier || segment.Type == CompositeLicenseExpressionSegmentType.ExceptionIdentifier;
    }

    public static MvcHtmlString GetExternalUrlAnchorTag(string data, string link)
    {
        return MvcHtmlString.Create(UriExtensions.GetExternalUrlAnchorTag(data, link));
    }
}